package ps.net;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import ps.server.net.ClientInfo;




public class Packet {
    
    public static final int TYPE_UNDEFINED = 0;
    public static final int TYPE_PING = 1;
    public static final int TYPE_ACKNOWLEGE = 2;
    public static final int TYPE_LOGIN = 3;
    public static final int TYPE_LOGOUT = 4;
    public static final int TYPE_MESSAGE = 5;
    public static final int TYPE_CLIENT_LIST = 6;
    public static final int TYPE_ADD_USER = 7;
    public static final int TYPE_REMOVE_USER = 8;
    public static final int TYPE_CHANGE_PASSWORD = 9;
    public static final int TYPE_CHANGE_USER_RIGHT = 10;
    public static final int TYPE_SERVER_CMD = 11;
    public static final int TYPE_CLIENT_INFO = 12;
    public static final int TYPE_CHAT = 13;
    public static final int TYPE_TRIGGER_DESC = 14;
    public static final int TYPE_TRIGGER_EVENT = 15;
    public static final int TYPE_DPS_PARSE = 16;
    
    public static final String ENCODING = "Cp1250";
    
    int type = Packet.TYPE_UNDEFINED;
	PacketContent content = null;
	
	long time = 0;
	
	ClientInfo sender;
	ClientInfo[] reciever = new ClientInfo[0];
	
	int resendCount = 0;

	public Packet() {
	}
	
	public Packet(ClientInfo sender) {
	    this.sender = sender;
	}
	
	public Packet(int type) {
	    this.type = type;
	}
	
	public void writePacket(OutputStream out) throws IOException {
	    // write type (1 byte)
        out.write(type);
        
        if (content != null) {
            content.writeContent(out);
        }
    }
	
	public void readPacket(InputStream in) throws IOException {
	    // get type
        type = in.read();
	    
        content = getInstanceByType(type);
        if (content != null) {
            content.readContent(in);
        }
	}
	
    @Override
    public String toString() {
        String ret = "[ type=" + type;
        ret += " ]";
        ret += content == null ? "[]" : content.toString();
        return ret;
    }
    
    private static PacketContent getInstanceByType(int type) {
        PacketContent ret = null;
        
        ret = type == Packet.TYPE_LOGIN ? new LoginContent() : ret;
        ret = type == Packet.TYPE_MESSAGE ? new MessageContent() : ret;
        ret = type == Packet.TYPE_CLIENT_LIST ? new ClientListContent() : ret;
        ret = type == Packet.TYPE_ADD_USER ? new AddUserContent() : ret;
        ret = type == Packet.TYPE_REMOVE_USER ? new RemoveUserContent() : ret;
        ret = type == Packet.TYPE_CHANGE_PASSWORD ? new ChangePasswordContent() : ret;
        ret = type == Packet.TYPE_CHANGE_USER_RIGHT ? new ChangeUserRightContent() : ret;
        ret = type == Packet.TYPE_SERVER_CMD ? new ServerCmdContent() : ret;
        ret = type == Packet.TYPE_CLIENT_INFO ? new ClientInfoContent() : ret;
        ret = type == Packet.TYPE_CHAT ? new ChatContent() : ret;
        ret = type == Packet.TYPE_TRIGGER_DESC ? new TriggerDescContent() : ret;
        ret = type == Packet.TYPE_TRIGGER_EVENT ? new TriggerEventContent() : ret;
        ret = type == Packet.TYPE_DPS_PARSE ? new DpsParseContent() : ret;
        
        return ret;
    }
    
	public static void writeString(OutputStream out, String str) throws IOException {
        byte[] strBytes = str.getBytes(ENCODING);
        if (strBytes.length > 255) {
            strBytes = str.substring(0, 255).getBytes(ENCODING);
        }
        
        out.write(strBytes.length);
        out.write(strBytes);
    }
	
    public static String readString(InputStream in) throws IOException {
        int length = in.read();
        
        byte[] bytes = new byte[length];
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte)in.read();
        }
        return new String(bytes, ENCODING);
    }
    
    public static void write2ByteNumber(OutputStream out, int number) throws IOException {
        short shortNumber = (short)number;
        
        out.write((byte)(shortNumber >>> 8)); 
        out.write((byte)shortNumber);
    }
    
    public static int read2ByteNumber(InputStream in) throws IOException {
        int b1 = in.read();
        int b2 = in.read();
        
        int number = (b1 << 8) + b2;
        
        return number;
    }
    
    public static void writeBoolean(OutputStream out, boolean b) throws IOException {
        out.write(b ? 1 : 0);
    }
    
    public static boolean readBoolean(InputStream in) throws IOException {
        return in.read() > 0;
    }
    
    public void setType(int type) {
        this.type = type;
    }
    
    public int getType() {
        return type;
    }
    
    public boolean isTypeOf(int type) {
        return this.type == type;
    }
    
    public PacketContent getContent() {
        return content;
    }
    
    public void setContent(PacketContent packetContent) {
        this.content = packetContent;
    }
    
    public long getTime() {
        return time;
    }

    public void setTime(long time) {
        this.time = time;
    }
    
    public void setResendCount(int resendCount) {
        this.resendCount = resendCount;
    }
    
    public int getResentCount() {
        return resendCount;
    }
    
    public ClientInfo getSender() {
        return sender;
    }
    
    public void setSender(ClientInfo sender) {
        this.sender = sender;
    }

    
    public ClientInfo[] getReciever() {
        return reciever;
    }

    
    public void setReciever(ClientInfo[] reciever) {
        this.reciever = reciever;
    }
    
    public void setReciever(ClientInfo reciever) {
        this.reciever = new ClientInfo[] { reciever };
    }
}
